<!doctype html>
<html>
	<head>
		<meta charset='UTF-8'>
		<meta name='viewport' content='width=device-width initial-scale=1'>
		<title></title>
		<link href='https://fonts.loli.net/css?family=Open+Sans:400italic,700italic,700,400&subset=latin,latin-ext' rel='stylesheet'
		 type='text/css' />
		<link rel="stylesheet" type="text/css" href="../css/wenzhang.css" />
		<link rel="stylesheet" type="text/css" href="../css/index.css"/>
	</head>
	<body>
		<div class="daohang">
			
			<div class="right">
				<ul class="daohang_ul">
					<li><a href="../index.html">首页</a></li>
					<li><a href="./wz00.html">设计要求</a></li>
					<li><a href="../gunyvwo.html">关于我</a></li>
					<li><a href="../xiangce.html">我的相册</a></li>
					<li><a href="../shopin1.html">喜欢的视频</a></li>
					<li><a href="../register.html">登录/注册</a></li>
				</ul>
			</div>
		</div>
		<div id='write' class=''>
			<h1><a name="汇编语言总结笔记" class="md-header-anchor"></a><span>汇编语言总结笔记</span></h1>
			<blockquote>
				<p><span>作者 liuy88141</span></p>
				<p>&nbsp;</p>
			</blockquote>
			<p><span>开始学习汇编语言，对相关的所学知识做个总结，希望对自己可以有所提高。</span></p>
			<p><strong><em><span>1、在计算机中数的表示方式</span></em></strong></p>
			<p><span>因为计算机中只能存储二进制数，所以一般都是通过二进制直接进行存储，但是为了方便阅读和程序员的编码简单化，就出现了八进制、十进制、十六进制，一般在汇编的学习过程中以二、十、十六进制为主。</span></p>
			<p><span>四种数据的表示形式符号是：B(二进制)、O(八进制)，D(十进制)，H(十六进制)</span></p>
			<p><span>二进制、八进制、十六进制转化为十进制都是通过数值为乘以权值，然后求和得出；</span></p>
			<p><span>十进制转换为相应的进制都是通过除以相应的基数取余后，逆序达到相关的表示法。</span></p>
			<p><span> </span></p>
			<p><strong><em><span>2、在计算中通常通过数值的原码、反码、补码来进行表示。</span></em></strong></p>
			<p><span>对于无符号数，讨论三码没有什么意义；</span></p>
			<p><span>对于有符号数，一般第一位代表的是符号位，0代表+，1代表—，同时在表示的过程中，因为存储器的位数可能存在数据为的扩展，一般都是扩展符号位。</span></p>
			<p><span>对于正整数而言，原码=反码=补码，符号扩展位为0；</span></p>
			<p><span>对于负整数而言，原码 按位取反 = 反码，反码+1 = 补码，符号位保证不变。</span></p>
			<p><span>求负数的补码一般有两种方法：</span></p>
			<p><span>（1）先写出其绝对值的原码，然后把符号位也参加在内进行取反，在加1即可。</span></p>
			<p><span>（2）按照上面给出负数的求补即可。</span></p>
			<p><span>补码的相关规则</span></p>
			<p><span>（a+b）补 = （a）补+（b）补</span></p>
			<p><span>（a-b）补 = （a）补-（b）补</span></p>
			<p><span> </span></p>
			<p><strong><em><span>3、对8086体系结构中寄存器的认识</span></em></strong></p>
			<p><strong><span>（1）存在14个16位的寄存器和8个8位寄存器</span></strong></p>
			<p><span>通用寄存器包括如下几类</span></p>
			<p><span>通用寄存器：传送、暂存数据和接受相关的运算结果。</span></p>
			<p><span>1、16位数据寄存器，保存操作数和操作结果，缩短了访问内存的时间和并且不会占用相关的系统总数</span></p>
			<p><span>AX(累加器、被除数的低16位和除法结果) = AH + AL(8位)&lt;两个独立的寄存器，下面的相同&gt;</span></p>
			<p><span>BX(基址寄存器) = BH + BL(8位)&lt;用于基址寻址，唯一一个作为存储器指针使用的寄存器&gt;</span></p>
			<p><span>CX(字符串操作、控制循环次数) = CH + CL (移位的时候使用，保存移位的位数)(8位)</span></p>
			<p><span>DX(32位乘除法，存放被除数的高16位，或者保留余数，AX保留结果) = DH + DL(8位)</span></p>
			<p><span>8个八位寄存器</span></p>
			<p><span>AH 、AL 、BH、 BL、 CH、 CL、 DH、 DL</span></p>
			<p><span> </span></p>
			<p><span>指针寄存器：存储某个存储单元的地址或者是一段存储单元的起始地址</span></p>
			<p><span>2、16位指针寄存器</span></p>
			<p><span>BP(基址指针 base point 堆栈数据区基址的偏移 )</span></p>
			<p><span>SP(堆栈指针 stack pointer &lt;push pop 指令的时候使用，保存栈顶地址&gt;) </span></p>
			<p><span>上面两个指针一般是和SS合用</span></p>
			<p><span> </span></p>
			<p><span>3、16位变值寄存器&lt;一般在字符串操作的时候用的比较多&gt;</span></p>
			<p><span>DI (目的地址 destination )</span></p>
			<p><span>SI(源地址 source)</span></p>
			<p><span> 上面的两个寄存器一般是和DS、ES合用</span></p>
			<p><span> </span></p>
			<p><span>控制寄存器</span></p>
			<p><span>IP(指令指针)&lt;下一条指令的地址，但是不代表是下次将会执行的指令&gt;</span></p>
			<p><span>在计算机的组成原理中还有PC(程序计数器，始终指向下一条将要执行的指令，有时候PC和IP的内容相同，有时候又不同，个人理解？)</span></p>
			<p><span> </span></p>
			<p><span>FLAG(标志寄存器)，其中包含了9个标志，主要反映存储器的状态和相关的运算状态</span></p>
			<p><span>前6个运算结果标志，后3个控制标志</span></p>
			<p><span>0 CF (carry flag ) 进位标志 反映运算是否产生进位或者借位&lt;加法和减法&gt;</span></p>
			<p><span>2 PF (parity flag ) 奇偶标志 反映运算结果中1的个数是奇数还是偶数(偶数则置为1)</span></p>
			<p><span>4 AF(assist flag ) 辅助标志 在字节操作中，发生低半字节向高半字节进位或借位；在字操作中，低半字向高半字进位或者借位</span></p>
			<p><span>6 ZF(zero flag ) 零标志 反映运算结果是否为0</span></p>
			<p><span>7 SF(signed flag )符号标志 反映运算结果的符号位，与运算结果的最高位相同</span></p>
			<p><span>11 OF(over flag) 溢出标志 反映有符号数加减运算是否引起溢出</span></p>
			<p><span> </span></p>
			<p><span>8 TF(trace flag ) 跟踪标志 置为1后，cpu进入单步方式。主要用于调试，cpu执行一条指令后被中断</span></p>
			<p><span>9 IF(interrupt flag)中断标志 决定CPU是否相应外部可屏蔽中断请求，1则响应，0则不响应</span></p>
			<p><span>10 DF(direction flag) 方向标志 决定串操作指令执行时有关指针寄存器调整方向，为1，则串操作指令按减方式改变有关寄存器的值，反之则用加方式</span></p>
			<p><span> </span></p>
			<p><span>16位段寄存器&lt;寻址1M的物理地址空间的时候需要使用它，在计算机的内存中代码&lt;指令&gt;和数据是放在不同的存储空间中&gt;</span></p>
			<p><span>放操作的数据</span></p>
			<p><span>DS(数据段，一般配合bx作为偏移 data segment)</span></p>
			<p><span>ES(附加段 extend segment)</span></p>
			<p><span> </span></p>
			<p><span>放指令</span></p>
			<p><span>CS(代码段，一般和IP连用 code segment)</span></p>
			<p><span> </span></p>
			<p><span>保存相关的寄存器值等，放在这里方便函数返回的时候在恢复现场</span></p>
			<p><span>SS(堆栈段 stack segment)</span></p>
			<p><span> </span></p>
			<p><strong><span>2、地址分段和寻址</span></strong><span> </span></p>
			<p><span>一、明确地址分段的原因</span></p>
			<p><span> 因为在8086中CPU的地址线是20位，那么实际可用的最大物理地址空间是1MB,但是因为寄存器都是只有16位和8位之分，最大寻址范围是64KB，为了寻找到所有的物理地址，需要对物理地址空间进行分段。</span></p>
			<p><span>分段一般是由段首地址+段内偏移地址组成。</span></p>
			<p><span>但是对于段的首地址不是随意乱取，通常都以“小段的起始地址为主”</span></p>
			<p><span>“小段”即是在物理地址中从00000H开始，每16个字节而划分的，那么整个物理地址空间就可以划分为64K个小段，且首地址的最后四位均为0（用二进制表示时），所以是16的倍数。</span></p>
			<p><span> </span></p>
			<p><span> 进行分段后，段与段之间就会有重叠、相邻、不会相干的现象产生。</span></p>
			<p><span>一般物理地址= 段首地址*16+段内偏移地址。</span></p>
			<p><span>前者为物理地址，后者断首地址：偏移地址为逻辑地址。所以</span><strong><em><span>*</span><span>一个物理地址可能对应多个逻辑地址</span><span>*</span></em></strong><span>的表示。</span></p>
			<p><span> </span></p>
			<p><span>二、寻址方式</span></p>
			<p><span>（1）汇编代码是由两部分组成：操作码+操作数</span></p>
			<p><span>一般操作码在相应的机器指令体系中有相关的表示，但是操作数的存储就会不同了。</span></p>
			<p><span>操作数存储在如下地方：</span></p>
			<p><span>一、直接在汇编代码中：那么这种寻址方式就是立即数寻址 mov ax, 1234H</span></p>
			<p><span>二、存放在寄存器中：那么这种寻址方式就是寄存器寻址 mov ax,bx</span></p>
			<p><span>三、存放在内存中，那么这种寻址方式就比较多了</span></p>
			<p><span> </span></p>
			<p><span> </span></p>
			<p><span>寻址方式：（以源操作数的寻址为例）</span></p>
			<p><span>1、立即数寻址 mov ax，1234H</span></p>
			<p><span>2、寄存器寻址 mov ax，bx</span></p>
			<p><span>3、直接寻址 mov ax，【1234H】 （ax） = （ds*16+1234H）</span></p>
			<p><span>4、寄存器间接寻址</span></p>
			<p><span>mov ax，【bx】 （ax） = （ds*16+bx）</span></p>
			<p><span>mov ax，【BP】 （ax）=（ss*16+bp）</span></p>
			<p><span>因为bp的默认是通过ss来寻址，不过也可以通过段地址前缀来进行强加了</span></p>
			<p><span>mov ax，ds:[BP] (ax) = (ds*16+bp)</span></p>
			<p><span>5、寄存器相对寻址</span></p>
			<p><span>mov ax,[bx+1234H] (ax) = (ds*16+bx+1234H)</span></p>
			<p><span>也可以表示为</span></p>
			<p><span>mov ax，1234H【bx】</span></p>
			<p><span>同4，也存在这样的关系</span></p>
			<p><span>6、基址变址寻址</span></p>
			<p><span>mov ax，【bx+si】 （ax）= （ds*16+bx+si） &lt;bx是基址寄存器，默认是和ds合用&gt;</span></p>
			<p><span>也可以表示为</span></p>
			<p><span>mov ax，【bx】【si】或者是mov ax，【si】【bx】</span></p>
			<p><span>7、相对基址变址寻址</span></p>
			<p><span>mov ax，【bx+si+1234H】 （ax）=（ds*16+bx+si+1234H）</span></p>
			<p><span> </span></p>
			<p><span>因为对于其中的很多寄存器都是可以变换的，所以不在这里一一列举</span></p>
			<p><span>但是对于以上7中寻址方式到底应该在什么情况下进行使用还需要进一步的学习。</span></p>
		</div>
	</body>
</html>
